#pragma once

#include<iostream>
#include<functional>
#include<pthread.h>
#include"Sock.hpp"
#include"Protocol.hpp"



namespace tcpserver_ns
{
    class TcpServer;

    using namespace protocol_ns;
    using func_t = std::function<Responce (const Request&)>;

    class ThreadDate
    {
    public:
        ThreadDate(int sock,std::string&clientIp,uint16_t clientPort,TcpServer*t)
        :_sock(sock),
        _clientIp(clientIp),
        _clientPort(clientPort),
        _tsvr(t)
        {}
    public:
        int _sock;
        std::string _clientIp;
        uint16_t _clientPort;
        TcpServer*_tsvr;
    };

    class TcpServer
    {
    public:
        TcpServer(uint16_t port,func_t func):_port(port),_func(func)
        {}

        void InitServer()
        {
            _listensock.Socket();
            _listensock.Bind(_port);
            _listensock.Listen();
        }
        //启动服务器
        void Start()
        {
            while(true)
            {
                std::string clientIp;
                uint16_t clientPort;
                int sock=_listensock.Accept(&clientIp,&clientPort);
                if(sock<0) continue;
                //多线程
                std::string name="["+clientIp+":"+std::to_string(clientPort)+"]";
                logMessage(Info,"accept client %s success",name.c_str());
                pthread_t pid;
                ThreadDate* td=new ThreadDate(sock,clientIp,clientPort,this);
                pthread_create(&pid,nullptr,ThreadRoutine,td);
            }
        }
        //线程启动函数
        static void* ThreadRoutine(void*args)
        {
            //分离
            pthread_detach(pthread_self());
            ThreadDate*td=static_cast<ThreadDate*>(args);
            td->_tsvr->ServerIO(td->_sock,td->_clientIp,td->_clientPort);

            delete td;
            return nullptr;
        }

        void ServerIO(int sock,const std::string& clientIp,const uint16_t& clientPort)
        {
            std::string inbuffer;//保存接收到的数据
            while(true)
            {
                std::string name = "[" + clientIp + ":" + std::to_string(clientPort) + "]";
                std::string package;//提取一个完整的报文
                //收数据
                int n=ReadPackage(sock,inbuffer,&package);
                if(n==0)
                    continue;
                else if(n==-1)
                {
                    logMessage(Warning,"%s quit",name.c_str());
                    break;
                }
                else if(n==-2)
                {
                    logMessage(Warning,"recv error,%s,errno:%d",strerror(errno),errno);
                    break;
                }

                package=RemoveHead(n,package);
                logMessage(Info,"%s# %s",name.c_str(),package.c_str());
                
                //需求反序列化
                Request req;
                req.Deserialize(package.c_str());
                //业务处理
                Responce resq=_func(req);

                //相应序列化
                std::string send_string;
                resq.Serialize(&send_string);
                send_string=AddHead(send_string);

                //发送数据
                send(sock,send_string.c_str(),send_string.size(),0);
            }
            close(sock);
        }

        ~TcpServer()
        {
            _listensock.Close();
        }
    private:
    Sock _listensock;
    uint16_t _port;
    func_t _func;
    };
}